package com.mz.mattress.client.plan;

import com.mz.mattress.api.entity.PlanTaskData;
import com.mz.mattress.api.redis.RedisKeys;
import com.mz.mattress.api.util.SpringUtil;
import com.mz.mattress.client.mapper.PlanTaskDataMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.*;

//任务执行器
@Slf4j
@Service
public class PlanExecuteService implements PlanTimer {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private PlanTaskDataMapper planTaskDataMapper;

    public static final ScheduledExecutorService EXECUTOR = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName("planExecuteThread");
            t.setDaemon(true);
            return t;
        }
    });

    @PostConstruct
    public void init() {

        int delay = isTest ? 5 : 10;

        EXECUTOR.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                runTask();

            }
        }, delay, delay, TimeUnit.SECONDS);

    }

    @Override
    public void runTask() {

        while (true) {
            try {

//                if (ThreadLocalRandom.current().nextInt(10) < 5) {
//                    log.info("plan_execute_running");
//                }

                Object object = redisTemplate.boundListOps(RedisKeys.PLAN_TASK_QUEUE).leftPop();
                if (object == null) {
                    log.info("plan_execute_task_queue_is_null");
                    //没任务 暂停，等下次
                    break;
                }

                PlanTaskData data = planTaskDataMapper.selectById(Integer.parseInt(object.toString()));
                if (data == null) {
                    log.info("plan_execute_data_is_null_id=" + object);
                    continue;
                }

                String beanName = data.getBeanName();

                Map<String, PlanExecutor> beansOfType = SpringUtil.getBeansOfType(PlanExecutor.class);
                PlanExecutor planExecutor = beansOfType.get(beanName);
                if (planExecutor == null) {
                    log.info("plan_execute_not_find_bean_name=" + beanName);
                    continue;
                }

                int delayTime = ThreadLocalRandom.current().nextInt(5);
                if (delayTime > 0) {
                    Thread.sleep(delayTime * 1000);
                }

                log.info("plan_execute_taskId=" + data.getId());

                planExecutor.doTask(data);

            } catch (Throwable e) {
                log.info("plan_execute_error", e);
            }
        }

    }

}
